package com.example.config;

import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.BlockExceptionHandler;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityException;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException;
import com.example.common.pojo.CommonResult; // 引入项目统一返回类
import cn.hutool.json.JSONUtil; // 复用父模块hutool工具类（确保sky-common已引入）
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;

import java.io.IOException;

/**
 * Sentinel统一异常处理配置
 * 适配项目CommonResult返回格式，处理限流、熔断、授权等Sentinel拦截异常
 */
@Configuration
@Slf4j
public class SentinelConfig implements BlockExceptionHandler {

    // ======================== 扩展Sentinel异常专属状态码（可选，便于前端区分异常类型）========================
    /** 限流异常状态码 */
    private static final int CODE_FLOW_LIMIT = 501;
    /** 熔断异常状态码 */
    private static final int CODE_DEGRADE = 502;
    /** 参数限流异常状态码 */
    private static final int CODE_PARAM_FLOW = 503;
    /** 授权异常状态码 */
    private static final int CODE_AUTHORITY = 403;
    /** 通用拦截异常状态码 */
    private static final int CODE_COMMON_BLOCK = 504;

    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws IOException {
        // 1. 设置响应头（确保JSON格式、跨域兼容）
        response.setContentType("application/json;charset=UTF-8");
        response.setCharacterEncoding("UTF-8");
        response.setStatus(HttpServletResponse.SC_OK); // HTTP状态码200（业务异常通过CommonResult的code区分）

        // 2. 区分Sentinel异常类型，构建对应CommonResult
        CommonResult<Void> result;
        if (e instanceof FlowException) {
            // 限流异常：使用专属状态码+提示
            result = CommonResult.get(CODE_FLOW_LIMIT, "当前请求人数过多，请稍后再试（限流）", null);
        } else if (e instanceof DegradeException) {
            // 熔断异常：服务降级，提示用户重试
            result = CommonResult.get(CODE_DEGRADE, "服务暂时不可用，请稍后再试（熔断）", null);
        } else if (e instanceof ParamFlowException) {
            // 参数限流：针对特定参数的流量控制
            result = CommonResult.get(CODE_PARAM_FLOW, "请求参数触发限流，请稍后再试", null);
        } else if (e instanceof AuthorityException) {
            // 授权异常：无访问权限（如IP黑名单、资源白名单限制）
            result = CommonResult.get(CODE_AUTHORITY, "无访问权限，请检查请求合法性", null);
        } else {
            // 其他拦截异常：通用提示
            result = CommonResult.get(CODE_COMMON_BLOCK, "系统繁忙，请稍后再试", null);
        }

        // 3. 打印异常日志（便于排查问题）
        log.error("Sentinel拦截异常 | 异常类型：{} | 请求路径：{} | 异常信息：{}",
                e.getClass().getSimpleName(), request.getRequestURI(), e.getMessage(), e);

        // 4. 响应结果写入流（使用hutool的JSONUtil确保格式正确，避免CommonResult.toString()的引号转义问题）
        response.getWriter().write(JSONUtil.toJsonStr(result));
    }
}